﻿#include "../../beans/headers/LineItemClass.h"
#include "../../views/headers/ItemScene.h"
#include "../../beans/headers/FlowBlockItem.h"
#include <QDebug>

LineItemClass::LineItemClass(DotItem *souDotItem ,DotItem *desDotItem,int lineItemID):
    m_LineItemID(lineItemID),
    m_SouDotItem(souDotItem),
    m_DesDotItem(desDotItem)
{
    initial();
}

LineItemClass::LineItemClass(DotItem *souDotItem ,DotItem *desDotItem,int lineItemID,QList<QPointF> linePoints_List):
    m_LineItemID(lineItemID),
    m_SouDotItem(souDotItem),
    m_DesDotItem(desDotItem)
{

    int linesCount = linePoints_List.count()-1;

    for (int i = 1; i < linesCount; i++)
    {
        FlowLineItem *lineItem = new FlowLineItem;
        QPointF begin_Pos = linePoints_List.at(i-1);
        QPointF end_Pos = linePoints_List.at(i);

        lineItem->setLine(QLineF(begin_Pos,end_Pos));
        lineItem->show();
        m_LineItems_List.append(lineItem);
    }

    this->m_TriangleItem = createTriangleItem();
}

LineItemClass::~LineItemClass(void)
{

}

// 辅助函数（初始化）
void LineItemClass::initial(void)
{
    // 新建5条线
    create5LineItems();

    this->m_TriangleItem = createTriangleItem();
}

// 创建箭头三角形
QGraphicsPolygonItem *LineItemClass::createTriangleItem(void)
{
    QGraphicsPolygonItem *triangleItem;

    triangleItem = new QGraphicsPolygonItem;
    m_SouDotItem->scene()->addItem(triangleItem);
    triangleItem->setZValue(-1);
    triangleItem->setCursor(Qt::DragLinkCursor);
    triangleItem->setData(ITEM_CLASS,EnumType::ItemClass_QGraphicsPolygonItem);

    // 设置画刷涂刷背景
    triangleItem->setBrush(QBrush(QColor(Qt::black)));

    return triangleItem;
}

// 辅助函数（获取每个LIneItem的碰撞的父级别BlockItem的列表）
QList<FlowBlockItem *> LineItemClass::collidingItems(FlowLineItem *lineItem)
{
    QList<QGraphicsItem *> blockItems_OldList;
    QList<FlowBlockItem *> flowBlockItems_List;
    QGraphicsItem *tempItem;

    blockItems_OldList = lineItem->scene()->collidingItems(lineItem);

    foreach (tempItem, blockItems_OldList)
    {
        if(tempItem->data(ITEM_CLASS).toInt() == EnumType::ItemClass_FLowBlockItem )
        {
            FlowBlockItem *flowBlockItem = qgraphicsitem_cast<FlowBlockItem *>(tempItem);
            flowBlockItems_List.append(flowBlockItem);
        }
    }

    return flowBlockItems_List;
}

// 辅助函数（画一条初始的曼哈顿路线:两个参数都是内联点，也就是端口中点偏离后的点）
void LineItemClass::drawManhattanLine(QPointF cursorPos)
{
    // 场景
    ItemScene *itemScene;

    // 源端口中心点 和 目标端口中心点
    QPointF souDotItemCentralPos,desDotItemCentralPos;

    // 源方向内联点 和 目标方向内联点
    QPointF souInlinePos,desInlinePos;

    // 源端口处的拐点
    QPointF inflectionPos_1,inflectionPos_2;

    // 五条线
    FlowLineItem *beginLine,*line2,*line3,*line4,*endLine;

    // 鼠标处的DotItem
    DotItem *cursorDotItem = Q_NULLPTR;

    // 源端口在BlockItem中的方位 和 目标端口在BlockItem中的方位
    int souDotItemDirection,desDotItemDirection;

    // souDotItem的外接圆半径
    qreal r;

    // 获取场景对象
    itemScene = qobject_cast<ItemScene *>( this->m_SouDotItem->scene());

    // 当没有目标端口时，就检测鼠标处是否有端口Item（一般用于起始画线，因为此时线的目标箭头是在鼠标处还不是DotItem）
    QGraphicsItem *tempItem = itemScene->itemAt(cursorPos,QTransform());

    if(tempItem != Q_NULLPTR && tempItem->data(ITEM_CLASS).toInt() == EnumType::ItemClass_DotItem)
        cursorDotItem = qgraphicsitem_cast<DotItem *>(tempItem);

    if(this->m_DesDotItem != Q_NULLPTR)
        cursorDotItem = this->m_DesDotItem;

    souDotItemCentralPos = m_SouDotItem->scenePos() + QPointF(DotItem::DOTITEM_WIDTH / 2,DotItem::DOTITEM_WIDTH / 2);
    souInlinePos = souDotItemCentralPos + QPointF(OFFSET_SIZE,OFFSET_SIZE);
    souDotItemDirection = m_SouDotItem->data(ITEM_TYPE).toInt();
    r = qSqrt(2) * DotItem::DOTITEM_WIDTH;
    beginLine = m_LineItems_List.at(0);
    line2 = m_LineItems_List.at(1);
    line3 = m_LineItems_List.at(2);
    line4 = m_LineItems_List.at(3);
    endLine = m_LineItems_List.at(4);

    // 如果鼠标距离和端口中心点距离小于端口外接圆半径就不画
    if(cursorPos.rx() <= r || cursorPos.ry() <= r)
        return;

    // 获取源内联点
    switch (souDotItemDirection)
    {
    case EnumType::DotItem_Top:
        souInlinePos.setX(souDotItemCentralPos.rx());
        souInlinePos.setY(souDotItemCentralPos.ry() - OFFSET_SIZE);
        break;
    case EnumType::DotItem_Bottom:
        souInlinePos.setX(souDotItemCentralPos.rx());
        souInlinePos.setY(souDotItemCentralPos.ry() + OFFSET_SIZE);
        break;
    case EnumType::DotItem_Left:
        souInlinePos.setX(souDotItemCentralPos.rx() - OFFSET_SIZE);
        souInlinePos.setY(souDotItemCentralPos.ry());
        break;
    case EnumType::DotItem_Right:
        souInlinePos.setX(souDotItemCentralPos.rx() + OFFSET_SIZE);
        souInlinePos.setY(souDotItemCentralPos.ry());
        break;
    default:

        break;
    }

    // 获取目标内联点
    if(cursorDotItem == Q_NULLPTR)
    {
        desInlinePos = cursorPos;
        desDotItemCentralPos = cursorPos;
    }
    else if(cursorDotItem != Q_NULLPTR)
    {
        desDotItemCentralPos = cursorDotItem->scenePos() + QPointF(DotItem::DOTITEM_WIDTH / 2,DotItem::DOTITEM_WIDTH / 2);
        desDotItemDirection = cursorDotItem->data(ITEM_TYPE).toInt();

        // 获取目标内联点
        switch (desDotItemDirection)
        {
        case EnumType::DotItem_Top:
            desInlinePos.setX(desDotItemCentralPos.rx());
            desInlinePos.setY(desDotItemCentralPos.ry() - OFFSET_SIZE);
            break;
        case EnumType::DotItem_Bottom:
            desInlinePos.setX(desDotItemCentralPos.rx());
            desInlinePos.setY(desDotItemCentralPos.ry() + OFFSET_SIZE);
            break;
        case EnumType::DotItem_Left:
            desInlinePos.setX(desDotItemCentralPos.rx() - OFFSET_SIZE);
            desInlinePos.setY(desDotItemCentralPos.ry());
            break;
        case EnumType::DotItem_Right:
            desInlinePos.setX(desDotItemCentralPos.rx() + OFFSET_SIZE);
            desInlinePos.setY(desDotItemCentralPos.ry());
            break;
        default:

            break;
        }
    }

    // 获取源处第一个拐点（此时不考虑任何碰撞问题）此时如果目标点和源内联点在一个直线上，拐点就和目标点重合。
    if(souDotItemDirection == EnumType::DotItem_Left || souDotItemDirection == EnumType::DotItem_Right)
    {
        // 如果begline的方向和desInliePos相对于souInlinePos的方向是相反的
        if((desInlinePos.rx() - souInlinePos.rx()) * (souInlinePos.rx() - souDotItemCentralPos.rx()) < 0)
        {
            inflectionPos_1.setX(souInlinePos.rx());
            inflectionPos_1.setY(desInlinePos.ry());
        }
        else
        {
            inflectionPos_1.setX(desInlinePos.rx());
            inflectionPos_1.setY(souInlinePos.ry());
        }
    }
    else if(souDotItemDirection == EnumType::DotItem_Top || souDotItemDirection == EnumType::DotItem_Bottom)
    {
        // 如果begline的方向和desInliePos相对于souInlinePos的方向是相反的
        if((desInlinePos.ry() - souInlinePos.ry()) * (souInlinePos.ry() - souDotItemCentralPos.ry()) < 0)
        {
            inflectionPos_1.setX(desInlinePos.rx());
            inflectionPos_1.setY(souInlinePos.ry());
        }
        else
        {
            inflectionPos_1.setX(souInlinePos.rx());
            inflectionPos_1.setY(desInlinePos.ry());
        }
    }

    // 第二个拐点
    inflectionPos_2 = desInlinePos;

    beginLine->setLine(QLineF(souDotItemCentralPos,souInlinePos));
    line2->setLine(QLineF(souInlinePos,inflectionPos_1));
    line3->setLine(QLineF(inflectionPos_1,inflectionPos_2));
    line4->setLine(QLineF(inflectionPos_2,desInlinePos));
    endLine->setLine(QLineF(desInlinePos,desDotItemCentralPos));

    // 修正箭头三角形指向
    correctTriangleItem();
}

// 辅助函数（曼哈顿路径避障规划）
void LineItemClass::manhattanRoutePlan()
{
    // 遍历每一条线(需要忽略首尾线)
    for(int i = 1;i<m_LineItems_List.size() - 1;i++)
    {
        FlowLineItem *lineItem = m_LineItems_List.at(i);

        // 跳过点线的情况
        if(lineItem->line().p1() != lineItem->line().p2())
        {
            this->collidingMove(lineItem,this->m_LineItems_List);
        }
    }
}

// 辅助函数（检测线如果碰撞就使其位移）
void LineItemClass::collidingMove(FlowLineItem *lineItem,QList<FlowLineItem *> lineItems_List)
{
    // 检查是否为有效线段
    if(m_DesDotItem == Q_NULLPTR)
        return ;

    // lineItem在QList中的下标
    int index;

    // 源端口中心点和目标端口中心点
    QPointF souPos,desPos;

    index = lineItems_List.indexOf(lineItem);
    souPos = m_SouDotItem->scenePos() + QPointF(DotItem::DOTITEM_WIDTH / 2,DotItem::DOTITEM_WIDTH / 2);
    desPos = m_DesDotItem->scenePos() + QPointF(DotItem::DOTITEM_WIDTH / 2,DotItem::DOTITEM_WIDTH / 2);

    // 检测线是否有碰撞的FlowBlockItem
    QList<FlowBlockItem *> blockItem_List = this->collidingItems(lineItem);

    if(blockItem_List.empty())
    {
        return ;
    }
    else
    {
        // 源模块和目标模块的中点坐标 以及碰撞的模块的中点坐标
        QPointF souBlockItemCentralPos,desBlockItemCentralPos,blockItemCentralPos;

        // blockItem：线段碰撞的BlockItem的第一个对象指针
        FlowBlockItem *blockItem,*souBlockItem,*desBlockItem;

        // 每次递归都取第一个，因为有可能避开这一个就可以了
        blockItem = blockItem_List.first();

        souBlockItem = qgraphicsitem_cast<FlowBlockItem *>(m_SouDotItem->parentItem());
        desBlockItem = qgraphicsitem_cast<FlowBlockItem *>(m_DesDotItem->parentItem());

        blockItemCentralPos = blockItem->scenePos() + QPointF(blockItem->boundingRect().width() / 2,blockItem->boundingRect().height() / 2);
        souBlockItemCentralPos =  souBlockItem->scenePos() + QPointF(souBlockItem->boundingRect().width() / 2,souBlockItem->boundingRect().height() / 2);
        desBlockItemCentralPos =  desBlockItem->scenePos() + QPointF(desBlockItem->boundingRect().width() / 2,desBlockItem->boundingRect().height() / 2);

        // true为竖直，false为水平
        // 如果是竖直线
        if(lineItem->isVH())
        {
            // 计算出目标模块相对于源模块中心点的竖直方向单位长度方向（1表示同方向，-1表示反方向）
            int flag = -(desBlockItemCentralPos.rx() - souBlockItemCentralPos.rx()) / qAbs(desBlockItemCentralPos.rx() - souBlockItemCentralPos.rx());

            switch (this->m_DesDotItem->data(ITEM_TYPE).toInt()) {
            case EnumType::DotItem_Top:

                break;
            case EnumType::DotItem_Bottom:

                break;
            case EnumType::DotItem_Left:
                flag = -1;
                break;
            case EnumType::DotItem_Right:
                flag = +1;
                break;
            default:
                break;
            }

            qreal x = blockItemCentralPos.rx() +(OFFSET_SIZE + blockItem->boundingRect().width() / 2) * flag;
            qreal y1 = lineItem->line().p1().ry();
            qreal y2 = lineItem->line().p2().ry();

            lineItem->setLine(x,y1,x,y2);
        }
        // 如果是水平线
        else
        {
            // 计算出目标模块相对于源模块中心点的水平方向单位长度方向（1表示同方向，-1表示反方向）
            int flag = (desBlockItemCentralPos.ry() - souBlockItemCentralPos.ry()) / qAbs(desBlockItemCentralPos.ry() - souBlockItemCentralPos.ry());

            switch (this->m_DesDotItem->data(ITEM_TYPE).toInt()) {
            case EnumType::DotItem_Top:
                flag = -1;
                break;
            case EnumType::DotItem_Bottom:
                flag = +1;
                break;
            case EnumType::DotItem_Left:

                break;
            case EnumType::DotItem_Right:

                break;
            default:
                break;
            }

            qreal y = blockItemCentralPos.ry() -(OFFSET_SIZE + blockItem->boundingRect().height() / 2) * flag;
            qreal x1 = lineItem->line().p1().rx();
            qreal x2 = lineItem->line().p2().rx();

            lineItem->setLine(x1,y,x2,y);
        }

        // 调整与当前线连接的前后两条线的链接点的坐标
        this->updateConnectiveLines(lineItem);

        // 调整存在不是正交线的情况
        this->fixLineItems(this->m_LineItems_List);

        // 递归调用（检查下一个碰撞的BlockItem）
        this->collidingMove(lineItem,lineItems_List);
    }
}

// 辅助函数（归并线元组:为了通用，采用通过点线来判断是否平行。其实更简单是的识别存储位的方式）
void LineItemClass::mergeRoute(void)
{
    // 需要被删除掉的线
    QList<FlowLineItem *> deleteList;

    // 判断当前项和下一项的线是否垂直（因为是曼哈顿路径不是垂直就是平行），因此这里i的边界需要-1
    for (int i = 1;i<m_LineItems_List.size() ;i++)
    {
        // 当前项
        FlowLineItem *frontLine  = m_LineItems_List.at(i-1);

        // 下一项
        FlowLineItem *behindLine  = m_LineItems_List.at(i);

        QPointF frontVector = frontLine->line().p2() - frontLine->line().p1();
        QPointF behindVector = behindLine->line().p2() - behindLine->line().p1();

        // 是否是点线
        bool isPointLine = (behindLine->line().p1() == behindLine->line().p2());

        // 判断是否垂直（如果是0就是垂直，也可以检测点线的情况）
        qreal judgeFactor = frontVector.rx() * behindVector.rx() + frontVector.ry() * behindVector.ry();

        judgeFactor = (isPointLine ? 1.0 : judgeFactor);

        bool flag = judgeFactor != 0.0;

        // 如果平行
        if(flag)
        {
            behindLine->setLine(QLineF(frontLine->line().p1(),behindLine->line().p2()));

            // 将需要删除的线存入List中
            deleteList.append(frontLine);
        }
    }

    // 移除并删除需要清除掉的线
    foreach (FlowLineItem *item, deleteList)
    {
        m_LineItems_List.removeOne(item);
        delete item;
        item = Q_NULLPTR;
    }

    // 设置线元组里面每条线的鼠标样式，首尾两条线不能别选中和移动，要在归并后调用
    this->setLineItemCursorStyleAndFlags();
}

// 辅助函数（设置线元组里面每条线的鼠标样式，首尾两条线不能别选中和移动，要在归并后调用）
void LineItemClass::setLineItemCursorStyleAndFlags(void)
{
    int size = this->m_LineItems_List.size();
    for (int i = 0; i < size; ++i) {

        FlowLineItem *lineItem = this->m_LineItems_List.at(i);

        // 如果线不是首尾两条线，说明是可以移动的，需要设置鼠标样式
        if(i > 0 && i <size-1)
        {

            if(lineItem->line().p1().rx() == lineItem->line().p2().rx())
                // 如果线是竖直的
                lineItem->setCursor(Qt::SplitHCursor);
            else
                // 如果线是水平的
                lineItem->setCursor(Qt::SplitVCursor);
        }else
        {
            lineItem->setCursor(Qt::PointingHandCursor);
            // lineItem->setFlags(lineItem->flags() &~ QGraphicsItem::ItemIsSelectable);
            lineItem->setFlags(lineItem->flags() &~ QGraphicsItem::ItemIsMovable);
        }
    }
}

// 辅助函数（根据最后一根线来将三角形矫正）
void LineItemClass::correctTriangleItem()
{
    // 小三角形尺寸
    qreal size = 8.0;

    // 小三角形底边的半边长
    qreal bedside = size / 2;

    qreal p1_bedside;

    FlowLineItem *endLineItem;
    int direction;

    // 小三角的三个顶点
    QPointF point1,point2,point3;

    // 反向遍历，找到最后一条不是点线的线
    for (auto iter = m_LineItems_List.rbegin();iter != m_LineItems_List.rend();iter++)
    {
        FlowLineItem *lineItem = *iter;
        if(lineItem->line().p1() != lineItem->line().p2())
        {
            endLineItem = lineItem;
            break;
        }
    }

    direction = endLineItem->lineDirection();

    // 箭头三角形直角顶点
    point1 = endLineItem->line().p2();

    // 因为为了让鼠标显示小三角形的鼠标样式，小三角形的中点与线元组最后一条线的p2点重合
    // 如果已经连线，就要将小三角形的顶点和线元组最后一条线的p2点重合
    p1_bedside = (this->m_DesDotItem != Q_NULLPTR ? 0:bedside);

    switch (direction)
    {
    case EnumType::LineItem_Left:
        point1 = point1 + QPointF(-p1_bedside,0);
        point2 = point1 + QPointF(size,-bedside);
        point3 = point1 + QPointF(size,bedside);
        break;
    case EnumType::LineItem_Down:
        point1 = point1 + QPointF(0,p1_bedside);
        point2 = point1 + QPointF(-bedside,-size);
        point3 = point1 + QPointF(bedside,-size);
        break;
    case EnumType::LineItem_Right:
        point1 = point1 + QPointF(p1_bedside,0);
        point2 = point1 + QPointF(-size,-bedside);
        point3 = point1 + QPointF(-size,bedside);
        break;
    case EnumType::LineItem_Up:
        point1 = point1 + QPointF(0,-p1_bedside);
        point2 = point1 + QPointF(-bedside,size);
        point3 = point1 + QPointF(bedside,size);

        break;
    default:
        break;
    }

    QVector<QPointF> points;
    points.append(point1);
    points.append(point2);
    points.append(point3);

    QPolygonF trianglePolygon(points);

    m_TriangleItem->setPolygon(trianglePolygon);
    m_TriangleItem->setBrush(QBrush(QColor(Qt::black)));
}

// 辅助函数（该条线移动，与其连接的前后线的连接点也要更新，注意，线元组的起始和末尾点不会成为参数）
void LineItemClass::updateConnectiveLines(FlowLineItem *lineItem)
{
    // 当前线在线元组中的下标
    int index;

    // 当前线的前一条线和后一条线
    FlowLineItem *frontLineItem,*behindLineItem;

    index = m_LineItems_List.indexOf(lineItem);

    // 线元组的首尾两条不能移动
    if(index == 0 || index == m_LineItems_List.size() - 1)
        return;

    frontLineItem = m_LineItems_List.at(index - 1);
    behindLineItem = m_LineItems_List.at(index + 1);

    frontLineItem->setLine(QLineF(frontLineItem->line().p1(),lineItem->line().p1()));
    behindLineItem->setLine(QLineF(lineItem->line().p2(),behindLineItem->line().p2()));
}

// 辅助函数（修正线元组：如果有不是正交线的情况）
void LineItemClass::fixLineItems(QList<FlowLineItem *> &m_LineItems_List)
{
    // 两个端口中心点
    QPointF souDotItemCentralPos,desDotItemCentralPos;

    // 两个端口在BlockItem的方位
    int souDotItemDirection,desDotItemDirection;

    // 起始点、源内联点、第一个拐点、第二个拐点、目标内联点和目标端口点
    QPointF beginPos,souInlinePos,inflectionPos_1,inflectionPos_2,desInlinePos,endPos;

    FlowLineItem *firstLineItem,*secondLineItem;

    bool firstLineIsCrossLine,lastLineIsCrossLine;

    souDotItemCentralPos = this->m_SouDotItem->scenePos() + QPointF(DotItem::DOTITEM_WIDTH / 2,DotItem::DOTITEM_WIDTH / 2);
    desDotItemCentralPos = this->m_DesDotItem->scenePos() + QPointF(DotItem::DOTITEM_WIDTH / 2,DotItem::DOTITEM_WIDTH / 2);

    souDotItemDirection = this->m_SouDotItem->data(ITEM_TYPE).toInt();
    desDotItemDirection = this->m_DesDotItem->data(ITEM_TYPE).toInt();

    beginPos = m_LineItems_List.at(0)->line().p1();
    souInlinePos = m_LineItems_List.at(1)->line().p1();
    inflectionPos_1 = m_LineItems_List.at(2)->line().p1();
    inflectionPos_2 = m_LineItems_List.at(3)->line().p1();
    desInlinePos = m_LineItems_List.at(4)->line().p1();
    endPos = m_LineItems_List.at(4)->line().p2();

    firstLineItem = m_LineItems_List.at(0);
    secondLineItem = m_LineItems_List.at(1);

    // 用于判断是该线是否是正交线
    QPointF firstLine_P1,firstLine_P2,lastLine_P1,lastLine_P2;

    firstLine_P1 = firstLineItem->line().p1();
    firstLine_P2 = firstLineItem->line().p2();
    lastLine_P1 = m_LineItems_List.at(4)->line().p1();
    lastLine_P2 = m_LineItems_List.at(4)->line().p2();

    firstLineIsCrossLine = (firstLine_P1.rx() == firstLine_P2.rx() || firstLine_P1.ry() == firstLine_P2.ry());
    lastLineIsCrossLine = (lastLine_P1.rx() == lastLine_P2.rx() || lastLine_P1.ry() == lastLine_P2.ry());

    // 如果首尾两条线都是正交线就不执行
    if(firstLineIsCrossLine && lastLineIsCrossLine)
    {
        return;
    }

    //souInlinePos = QPointF(secondLineItem->line().p1().rx(),firstLineItem->line().p1().ry());

    // 获取源内联点
    switch (souDotItemDirection)
    {
    case EnumType::DotItem_Top:
        souInlinePos.setX(souDotItemCentralPos.rx());
        souInlinePos.setY(souDotItemCentralPos.ry() - OFFSET_SIZE);
        break;
    case EnumType::DotItem_Bottom:
        souInlinePos.setX(souDotItemCentralPos.rx());
        souInlinePos.setY(souDotItemCentralPos.ry() + OFFSET_SIZE);
        break;
    case EnumType::DotItem_Left:
        souInlinePos.setX(souDotItemCentralPos.rx() - OFFSET_SIZE);
        souInlinePos.setY(souDotItemCentralPos.ry());
        break;
    case EnumType::DotItem_Right:
        souInlinePos.setX(souDotItemCentralPos.rx() + OFFSET_SIZE);
        souInlinePos.setY(souDotItemCentralPos.ry());
        break;
    default:

        break;
    }

    // 获取目标内联点
    switch (desDotItemDirection)
    {
    case EnumType::DotItem_Top:
        desInlinePos.setX(desDotItemCentralPos.rx());
        desInlinePos.setY(desDotItemCentralPos.ry() - OFFSET_SIZE);
        break;
    case EnumType::DotItem_Bottom:
        desInlinePos.setX(desDotItemCentralPos.rx());
        desInlinePos.setY(desDotItemCentralPos.ry() + OFFSET_SIZE);
        break;
    case EnumType::DotItem_Left:
        desInlinePos.setX(desDotItemCentralPos.rx() - OFFSET_SIZE);
        desInlinePos.setY(desDotItemCentralPos.ry());
        break;
    case EnumType::DotItem_Right:
        desInlinePos.setX(desDotItemCentralPos.rx() + OFFSET_SIZE);
        desInlinePos.setY(desDotItemCentralPos.ry());
        break;
    default:

        break;
    }

    // 需要重新设置两个拐点
    inflectionPos_1 = secondLineItem->line().p1();
    inflectionPos_2 = secondLineItem->line().p2();

    m_LineItems_List.at(0)->setLine(QLineF(beginPos,souInlinePos));
    m_LineItems_List.at(1)->setLine(QLineF(souInlinePos,inflectionPos_1));
    m_LineItems_List.at(2)->setLine(QLineF(inflectionPos_1,inflectionPos_2));
    m_LineItems_List.at(3)->setLine(QLineF(inflectionPos_2,desInlinePos));
    m_LineItems_List.at(4)->setLine(QLineF(desInlinePos,endPos));
}

// 清楚5条线
void LineItemClass::clearLineItems(void)
{
    qDeleteAll(this->m_LineItems_List);
    this->m_LineItems_List.clear();

    delete m_TriangleItem;
    m_TriangleItem = Q_NULLPTR;
}

// 新建五条线
void LineItemClass::create5LineItems(void)
{
    // 源端口中心点
    QPointF souDotItemPos = m_SouDotItem->scenePos();

    QPointF souDotItemCentralPos = souDotItemPos + QPointF(DotItem::DOTITEM_WIDTH / 2,DotItem::DOTITEM_WIDTH / 2);

    // 初始化生成5条线(点都为源端口中心点)
    for(int i = 0;i<5;i++)
    {
        FlowLineItem *line = new FlowLineItem;
        QGraphicsScene *scene = m_SouDotItem->scene();
        scene->addItem(line);
        line->setLine(QLineF(souDotItemCentralPos,souDotItemCentralPos));
        line->show();
        m_LineItems_List.append(line);
    }
}

// 转换json对象
QJsonObject LineItemClass::toJsonObj(void)
{
    FlowBlockItem *souBlockItem,*desBlockItem;
    int souBlockItemID,desBlockItemID;

    QJsonObject jsonObj;
    QJsonArray linePos;

    souBlockItem = qgraphicsitem_cast<FlowBlockItem *>(m_SouDotItem->parentItem());
    desBlockItem = qgraphicsitem_cast<FlowBlockItem *>(m_DesDotItem->parentItem());
    souBlockItemID = souBlockItem->FlowBlockItemID();
    desBlockItemID = desBlockItem->FlowBlockItemID();

    jsonObj.insert("LineItem_ID",QJsonValue(m_LineItemID));

    for(int i = 0;i < m_LineItems_List.size() - 1;i++)
    {
        qreal posX = m_LineItems_List.at(i)->line().p2().rx();
        qreal posY = m_LineItems_List.at(i)->line().p2().ry();

        linePos.append(QJsonValue(posX));
        linePos.append(QJsonValue(posY));
    }

    jsonObj.insert("LineItem_Pos",QJsonValue(linePos));
    jsonObj.insert("LineItem_SouBlockItemID",QJsonValue(souBlockItemID));
    jsonObj.insert("LineItem_DesBlockItemID",QJsonValue(desBlockItemID));
    jsonObj.insert("LineItem_SouDotItemDirection",QJsonValue(m_SouDotItem->data(ITEM_TYPE).toInt()));
    jsonObj.insert("LineItem_DesDotItemDirection",QJsonValue(m_DesDotItem->data(ITEM_TYPE).toInt()));

    return jsonObj;
}

QList<FlowLineItem *> LineItemClass::LineItems_List() const
{
    return m_LineItems_List;
}

DotItem *LineItemClass::DesDotItem() const
{
    return m_DesDotItem;
}

void LineItemClass::setDesDotItem(DotItem *DesDotItem)
{
    m_DesDotItem = DesDotItem;
}

DotItem *LineItemClass::SouDotItem() const
{
    return m_SouDotItem;
}

void LineItemClass::setSouDotItem(DotItem *SouDotItem)
{
    m_SouDotItem = SouDotItem;
}

int LineItemClass::LineItemID() const
{
    return m_LineItemID;
}

void LineItemClass::setLineItemID(int LineItemID)
{
    m_LineItemID = LineItemID;
}
